package vector;

/**
 * This is class which is used for dealing with all the operation for a vector.
 * 
 * @author Yuting Wu
 * @author Kan Lin
 * @author Bing Dong
 * @version 0.1
 * 
 * 
 * @param xPos
 *            the x coordinate of a vector
 * 
 * @param yPos
 *            the y coordinate of a vector
 * 
 * @param zPos
 *            the z coordinate of a vector
 * 
 */
public class Vector {

	private final double xPos;
	private final double yPos;
	private final double zPos;

	/**
	 * @param xPostion
	 *            the x coordinate of a vector
	 * @param yPostion
	 *            the y coordinate of a vector
	 * @param zPosition
	 *            the z coordinate of a vector
	 */
	public Vector(final double xPostion, final double yPostion,
			final double zPosition) {
		xPos = xPostion;
		yPos = yPostion;
		zPos = zPosition;
	}

	/**
	 * @param vec
	 *            the v represents a vector
	 */
	public Vector(final Vector vec) {
		xPos = vec.xPos;
		yPos = vec.yPos;
		zPos = vec.zPos;
	}

	public double[] getVector() {
		double[] content = new double[3];
		content[0] = xPos;
		content[1] = yPos;
		content[2] = zPos;
		return content;
	}

	/**
	 * Overwrite toString method
	 * 
	 * @return a string contains x,y,z information
	 */
	public String toString() {
		return "Vector: x: " + this.xPos + ";y: " + this.yPos + ";z: "
				+ this.zPos;

	}

	/**
	 * @param vector
	 *            the input vector that wants to addto the current vector
	 * @return the vector which was added by the input vector
	 */
	public Vector add(final Vector vector) {
		return new Vector(xPos + vector.xPos, yPos + vector.yPos, zPos
				+ vector.zPos);

	}

	/**
	 * 
	 * @param vector
	 *            the input vector that wants to be subtracted by the current
	 *            vector
	 * @return the vector which was subtracted
	 */
	public Vector subtract(final Vector vector) {
		return new Vector(xPos - vector.xPos, yPos - vector.yPos, zPos
				- vector.zPos);
	}

	/**
	 * @param vector
	 *            the input vector that wants to crossProduct the current vector
	 * @return the vector which was crossproducted by the input vector
	 */
	public Vector crossProduct(final Vector vector) {
		return new Vector(yPos * vector.zPos - zPos * vector.yPos, zPos
				* vector.xPos - xPos * vector.zPos, xPos * vector.yPos - yPos
				* vector.xPos);
	}

	/**
	 * @param vector
	 *            the input vector that wants to dotProdcut the current vector
	 * @return the value which was dotproducted by the input vector
	 */
	public double dotProduct(final Vector vector) {
		return (xPos * vector.xPos + yPos * vector.yPos + zPos * vector.zPos);

	}

	/**
	 * @param value
	 *            the input value that wants to multiply the current vector
	 * @return the vector which was multiplied by the input vector
	 */
	public Vector multiply(final double value) {
		return new Vector(xPos * value, yPos * value, zPos * value);
	}

	/**
	 * @return the vector which was normalised
	 */
	public Vector normalise() {
		return this.multiply(1 / this.vectorLength());
	}

	/**
	 * @return the vector which was divided
	 */
	public Vector divide(final double div) {
		Vector product = new Vector(this.xPos / div, this.yPos / div, this.zPos
				/ div);
		return product;
	}

	/**
	 * @return the result of the operation of calculate the vector length
	 */
	public double vectorLength() {
		double lengthSq = xPos * xPos + yPos * yPos + zPos * zPos;
		return Math.sqrt(lengthSq);
	}

	public boolean objectEqual(Vector vec) {
		double[] vecVal = vec.getVector();
		// prevent mistake of the number in the end
		return ((Math.abs(xPos - vecVal[0]) < 0.000001)
				&& (Math.abs(yPos - vecVal[1]) < 0.0000001) && (Math.abs(zPos
				- vecVal[2]) < 0.0000001));
		// return ((xPos == vecVal[0])&&(yPos == vecVal[1])&&(zPos ==
		// vecVal[2]));

	}
}
